#ifndef OPENGL_RENDER_INTERFACE_H
#define OPENGL_RENDER_INTERFACE_H

#include "RenderInterface.h"
//#include "abUtil.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <list>
using namespace std;

class DecoSavedRenderState
{
	friend class DecoOpenGLRenderInterface;
private:
	matrix44 m_transform[TT_Max];
	DecoCullMode m_cullMode;
	INT m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight;
	DecoColor m_color;
	BOOL m_depthTest;
	BOOL m_texture;
	DecoRenderState m_state;
	DecoRenderType m_renderType;
	DecoLogicOp m_logicOp;
	DecoStencilState m_stencilState;
public:
	DecoSavedRenderState() : m_cullMode(CM_None), m_viewportX(0), m_viewportY(0), m_viewportWidth(0), m_viewportHeight(0),
							 m_color(0x00000000), m_depthTest(TRUE), m_texture(FALSE), m_renderType(RT_Opaque), m_logicOp(LO_NoOp), m_stencilState(SS_None)
	{
		for (size_t i = static_cast<size_t>(TT_LocalToWorld); i < static_cast<size_t>(TT_Max); i++)
		{
			m_transform[i].identity();
		}
	}
	friend DecoArchive& operator<< (DecoArchive& Ar, const DecoSavedRenderState& state);
	friend DecoArchive& operator>> (DecoArchive& Ar, DecoSavedRenderState& state);
};

class DecoOpenGLRenderInterface : public DecoRenderInterface
{
private:
	DecoSavedRenderState CurrentRenderState;
	list<DecoSavedRenderState>SavedRenderStates;
	void BindState(DecoRenderState State);


public:
	virtual ~DecoOpenGLRenderInterface();

	virtual void Initialize();
	virtual void Destroy();
	virtual void PushState(DecoRenderState State = RS_All);
	virtual void PopState(DecoRenderState State = RS_All);

	//virtual BOOL SetRenderTarget(FRenderTarget* RenderTarget);

	virtual void SetViewport(INT X,INT Y,INT Width,INT Height);
	virtual void GetViewport(INT& X, INT& Y, INT &Width, INT& Height);

	virtual void Clear(BOOL UseColor = 1, DecoColor color = DecoColor(255,255,255),BOOL UseDepth = 1,FLOAT Depth = 1.0f, BOOL UseStencil = 1, INT Stencil = 0);

	virtual void SetCullMode(DecoCullMode CullMode);

	virtual void SetAmbientLight(const DecoColor& AmbColor);
	virtual void SetLight(INT LightIndex, const DecoLight* light);
	virtual void ResetLight();
	virtual void EnableDepthTest(BOOL bEnable);
	virtual void EnableTexture(BOOL bEnable);
	virtual void EnablePxLogicOp(DecoLogicOp op);

	virtual void SetTransform(DecoTransformType Type, matrix44& Matrix);
	virtual void GetTransform(DecoTransformType Type, matrix44& Matrix);

	virtual void SetMaterial(const DecoMaterial& material);
	virtual void SetStencilState(DecoStencilState state);
	virtual void SetColor(const DecoColor& color);
	virtual void DrawPrimitive(DecoPrimitiveType PrimitiveType, size_t NumPrimitives, DecoDrawType DrawType, DecoVertexBuffer* VB, DecoIndexBuffer* IB = NULL);
	//virtual void DrawPrimitive(const AbVecList& meshPts, const AbVecList& normals, const AbTriList& triangles);
	virtual void BeginRenderType(DecoRenderType type);
	virtual void EndRenderType();
	virtual void SetReflectionConstraint(DecoRenderData* constraint);
	virtual void SaveToImage(const char * filename, DecoBufferType buffType = BT_Back);
	virtual void SetLineWidth(FLOAT n);
	virtual void ReadFrameBuffer(DecoBufferType buffType, DecoColorChannel ch, void* pixels);
	virtual void WriteFrameBuffer(INT x, INT y, INT wid, INT ht, DecoBufferType buffType, DecoColorChannel ch, void* pixels);
	friend DecoArchive& operator<< (DecoArchive& Ar, const DecoOpenGLRenderInterface& RI);
	friend DecoArchive& operator>> (DecoArchive& Ar, DecoOpenGLRenderInterface& RI);

};
#endif
